use actix_web::{
    get, post,
    web::{self, Query, ServiceConfig},
};
use serde::Deserialize;

use crate::{
    error::AppErr,
    store::hex::{self, Hex},
    web::{
        res::Download,
        utils::{new_cbor, Cbor, CborRet, Void, VoidRet},
    },
};

#[derive(Debug, Deserialize)]
struct HexCreateReq {
    pro_id: i64,
    name: String,
    version: String,
    description: String,
    target: String,

    #[serde(with = "serde_bytes")]
    body: Box<[u8]>,
}

#[post("/create")]
async fn on_create(req: Cbor<HexCreateReq>) -> CborRet<i64> {
    let id = hex::create(
        &req.name,
        req.pro_id,
        &req.version,
        &req.description,
        &req.target,
        &req.body,
    )
    .await?;
    new_cbor(id)
}

#[derive(Debug, Deserialize)]
struct HexQueryReq {
    pro_id: i64,
}

#[get("/query")]
async fn on_query(req: Query<HexQueryReq>) -> CborRet<Box<[Hex]>> {
    let hexs = hex::query(req.pro_id).await?;
    new_cbor(hexs)
}

#[post("/del")]
async fn on_del(id: Cbor<i64>) -> VoidRet {
    hex::del(*id).await?;
    Ok(Void)
}

#[derive(Debug, Deserialize)]
struct IdReq {
    id: i64,
}

#[get("/get")]
async fn on_get(id: Query<IdReq>) -> Result<Download, AppErr> {
    let (name, body) = hex::get(id.id).await?;
    Ok(Download::new(name, body))
}

pub fn register(cfg: &mut ServiceConfig) {
    let scope = web::scope("/hex")
        .service(on_query)
        .service(on_del)
        .service(on_create)
        .service(on_get);
    cfg.service(scope);
}
